/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.logging;

import org.zhiqim.kernel.constants.SignConstants;
import org.zhiqim.kernel.model.maps.HashMapCV;
import org.zhiqim.kernel.model.maps.HashMapSV;
import org.zhiqim.kernel.util.DateTimes;

/**
 * 日志工厂，通过名称或类获取对应的日志类
 * 
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
public final class LogFactory implements SignConstants, LogConstants
{
    private static final Object lock = new Object();
    private static final HashMapCV<Log> classMap = new HashMapCV<>();
    private static final HashMapSV<Log>  nameMap = new HashMapSV<>();
    
    //定义日志服务变量
    private static LogService logService;
    
    /**
     * 指定类获取对应的日志类
     * 
     * @param cls       指定的类
     * @return          日志类
     */
    public static final Log getLog(Class<?> cls)
    {
        Log log = classMap.get(cls);
        if (log != null)
            return log;
        
        synchronized (lock)
        {
            if (logService == null)
                logService = new LogServerDefault();
            
            log = new Log(cls, logService);
            classMap.put(cls, log);
        }
        
        return log;
    }
    
    /**
     * 指定名称获取对应的日志类
     * 
     * @param name      指定的名称
     * @return          日志类
     */
    public static final Log getLog(String name)
    {
        Log log = nameMap.get(name);
        if (log != null)
            return log;
        
        synchronized (lock)
        {
            if (logService == null)
                logService = new LogServerDefault();
            
            log = new Log(name, logService);
            nameMap.put(name, log);
        }
        
        return log;
    }

    /**
     * 当注册了日志服务时，支持更新日志服务
     * 
     * @param service   日志服务
     */
    public static final void updateLogService(LogService service)
    {
        synchronized (lock)
        {
            logService = service;
            
            for (Log log : classMap.values())
            {
                log.setLogService(logService);
            }
            
            for (Log log : nameMap.values())
            {
                log.setLogService(logService);
            }
        }
    }
    
    /**
     * 格式化日志信息，%m消息，%d时间，%t线程，%l级别，%n回车换行
     * 
     * @param pattern   模式字符串
     * @param message   消息内容
     * @param level     消息等级
     * @return          格式化之后的消息内容
     */
    public static final String format(String pattern, String message, String level)
    {
        StringBuilder strb = new StringBuilder();
        for (int i=0;i<pattern.length();i++)
        {
            char c = pattern.charAt(i);
            if (c != '%' || i == pattern.length()-1)
            {//不是格式化字符或最后一个字符
                strb.append(c);
                continue;
            }
            
            char c2 = pattern.charAt(i+1);
            switch (c2)
            {
            case 'm':strb.append(message);i++;break;
            case 'd':strb.append(DateTimes.getDateTimeSSSString());i++;break;
            case 'l':strb.append(level);i++;break;
            case 't':strb.append(Thread.currentThread().getName());i++;break;
            case 'n':strb.append(_BR_);i++;break;
            default:strb.append(c);break;
            }
        }
        
        return strb.toString();
    }
    
    /** 通过级别信息获取级别编号 */
    public static final int getLevel(String levelInfo)
    {
        if (DEBUG_STR.equalsIgnoreCase(levelInfo))
            return DEBUG;
        else if (INFO_STR.equalsIgnoreCase(levelInfo))
            return INFO;
        else if (ERROR_STR.equalsIgnoreCase(levelInfo))
            return ERROR;
        else if (WARN_STR.equalsIgnoreCase(levelInfo))
            return WARN;
        else if (FATAL_STR.equalsIgnoreCase(levelInfo))
            return FATAL;
        else 
            return UNKNOWN;
    }
    
    /** 通过级别编号获取级别信息 */
    public static final String getLevel(int level)
    {
        switch (level)
        {
        case DEBUG:return DEBUG_STR;
        case INFO:return INFO_STR;
        case ERROR:return ERROR_STR;
        case WARN:return WARN_STR;
        case FATAL:return FATAL_STR;
        default:return UNKNOWN_STR;
        }
    }
}
